using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Text;

using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

using BestHTTP;
using BestHTTP.WebSocket;
using BestHTTP.Cookies;
using pEventBus;
using Google.Protobuf;
using Google.Protobuf.Collections;

using Io.Marsdigital.CommonProtocol.Pb;
using Com.Shinian.FcgProtocol.Pb;
using FCG.cache.proxy_model;
using Network;
using GF.Debug;


public class WebSocketConnect : MonoSingleton<WebSocketConnect>
{
    string url;
    int uid;
    string tokenStr;
    WebSocket webSocket;
    bool isReconnect = false;
    int reconnectCount = 0;

    public void lobbyLogin(string ip, int port, int _uid, byte[] token)
    {
        url = "ws://" + ip + ":" + port;
        uid = _uid;
        tokenStr = Convert.ToBase64String(token);
        CreateWebSocketConnect();
    }

    void OnClosed(WebSocket ws, UInt16 code, string message)
    {
        Debug.Log("网络连接已关闭");
    }

    void OnOpen(WebSocket ws)
    {
        Debugger.Log("网络连接建立");
        if (isReconnect)
        {
            //UIMgr.PopView(ViewNames.WarnTip).GetComponent<WarnPanel>().Init("重连成功", 1);
            reconnectCount = 0;
        }
        else {
            EventBus<WSHandShakeSuccessEvent>.Raise(new WSHandShakeSuccessEvent()
            {
                playerUId = uid
            });
        }
        isReconnect = false;
    }

    void OnMessageReceived(WebSocket ws, byte[] data)
    {
        //Debug.Log("ws received size:" + data.Length);
        //byte[] data2 = null;
        //int length = Utility.Gzip_DecompressData(data, out data2);
        //byte[] data3 = new byte[length];
        //Array.Copy(data2, data3, length);
        NetMessageO msg = NetMessageO.Parser.ParseFrom(data);
        if (msg.Channel == (ushort)CommonChannel.EPmPack)
        {
            WebSocketManager.instance.handlerPMMessage(msg);
        }
        else
        {
            if (msg.Channel == (ushort)CommonChannel.ESyncTime)
            {
                Pack((short)CommonChannel.ESyncTime, msg.Data.ToByteArray());
            }
            else if (msg.Channel == (ushort)CommonChannel.EPingTime)
            {
                PingTimeDTO pingTimeDTO = PingTimeDTO.Parser.ParseFrom(msg.Data);
                //Debug.Log("ping:" + pingTimeDTO.Ping);
            }
        }
    }

    void OnError(WebSocket ws, Exception ex)
    {
        Debug.Log("网络断开:" + ex.Message);

        //UIMgr.PopView(ViewNames.WarnTip).GetComponent<WarnPanel>().Init("网络断开", 3, delegate ()
        //{
        //    ReConnect();
        //});
    }

    void CreateWebSocketConnect()
    {
        if (url != null) {
            webSocket = new WebSocket(new System.Uri(url), "", "");
            webSocket.InternalRequest.Cookies.Add(new Cookie("TOKEN", WWW.EscapeURL(tokenStr)));
            webSocket.InternalRequest.Cookies.Add(new Cookie("PLATFORM_ID", uid.ToString()));
            webSocket.OnClosed += OnClosed;
            webSocket.OnOpen += OnOpen;
            webSocket.OnBinary += OnMessageReceived;
            webSocket.OnError += OnError;
            webSocket.Open();
        }
    }

    void ReConnect()
    {
        reconnectCount += 1;
        //if (reconnectCount > 3) {
        //    UIMgr.PopView(ViewNames.WarnTip).GetComponent<WarnPanel>().Init("尝试重连失败3次", 1, delegate ()
        //    {
        //        isReconnect = false;
        //        reconnectCount = 0;
        //        webSocket = null;
        //        UIMgr.OpenScene("StartScene");
        //    });
        //    return;
        //}
        //UIMgr.PopView(ViewNames.WarnTip).GetComponent<WarnPanel>().Init("正在尝试重连..." + reconnectCount + "次", 1, delegate () {
        //    isReconnect = true;
        //    CreateWebSocketConnect();
        //});
    }

    void Send(byte[] data)
    {
        if (webSocket != null)
        {
            if (isReconnect)
            {
                ReConnect();
            }
            else
            {
                Debug.Log("ws send size:" + data.Length);
                webSocket.Send(data);
            }
        }
    }

    public void Close()
    {
        webSocket.Close();
        webSocket = null;
    }

    public void Pack(short channel)
    {
        if (channel != 31 && channel != 32)
            Debugger.Log("发送协议" + channel);
        NetMessageI msg = new NetMessageI();
        msg.Channel = channel;
        IdentifyI identify = new IdentifyI();
        identify.UserId = uid;
        msg.Identify = identify;
        byte[] data = new byte[msg.CalculateSize()];
        CodedOutputStream stream = new CodedOutputStream(data);
        msg.WriteTo(stream);
        Send(data);
    }

    public void Pack(short channel, byte[] data)
    {
        if (channel != 31 && channel != 32)
            Debugger.Log("发送协议" + channel + "带参数");
        NetMessageI msg = new NetMessageI
        {
            Channel = channel,
            Param = ByteString.CopyFrom(data),
            Identify = new IdentifyI
            {
                UserId = uid
            }
        };
        byte[] enddata = new byte[msg.CalculateSize()];
        CodedOutputStream stream = new CodedOutputStream(enddata);
        msg.WriteTo(stream);
        Send(enddata);
    }
}
